package com.rambler.gateway.interceptor;

import com.rambler.common.entity.GlobalConst;
import com.rambler.common.entity.TokenVerifyResult;
import com.rambler.common.utils.JWTUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.util.Arrays;
import java.util.List;
import java.util.Objects;

/**
 * @author suhao
 * @date 2025/8/25
 * @description 鉴权拦截器
 */
@Component
@Slf4j
public class JwtAuthFilter implements GlobalFilter, Ordered {

    @Value("${system.accessTokenExpireHours}")
    private String tokenExpireHours;

    // 过期前多少毫秒刷新,  默认5小时
    private static final long REFRESH_THRESHOLD = 5 * 60 * 60;

    public static final List<String> WHITE_LIST = Arrays.asList(
            "/api/common/system/user/oauth",
            "/api/common/system/register"
    );

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {

        // 白名单放行
        if (WHITE_LIST.contains(exchange.getRequest().getPath().value())) {
            log.info("白名单放行: {}", exchange.getRequest().getPath().value());
            return chain.filter(exchange);
        }

        log.info("校验Token, 请求路径: {}", exchange.getRequest().getPath().value());

        // 获取Token
        String token = exchange.getRequest().getHeaders().getFirst("Authorization");

        if (token == null || !token.startsWith("Bearer ")) {
            return unauthorized(exchange.getResponse());
        }

        // 去掉 Bearer 前缀
        token = token.substring(7);

        // 校验Token
        TokenVerifyResult result = JWTUtil.verify(token);
        if (!Objects.equals(result.getCode(), GlobalConst.SUCCESS)) {
            return unauthorized(exchange.getResponse());
        }

        // 如果快过期, 就重新生成一个新Token
        long expiresTime = result.getExpiresTime();
        if (expiresTime <= REFRESH_THRESHOLD) {
            log.info("Token快过期, 重新生成Token");
            String newToken = JWTUtil.getToken(result.getData(), Integer.valueOf(tokenExpireHours));
            exchange.getResponse().getHeaders().add("X-New-Token", newToken);
        }

        return chain.filter(exchange);
    }

    private Mono<Void> unauthorized(ServerHttpResponse response) {
        response.setStatusCode(HttpStatus.UNAUTHORIZED);
        return response.setComplete();
    }

    @Override
    public int getOrder() {
        // 优先级高
        return -1;
    }
}